package com.cmfi.service.impl;

import java.io.IOException;
import java.time.Instant;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.atomic.AtomicBoolean;

import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.cmfi.dao.PlanWorkOrderDao;
import com.cmfi.dao.PlcDao.PlcDao;
import com.cmfi.dao.PlcDao.PlcNodeDao;
import com.cmfi.domain.PlanWorkOrder;
import com.cmfi.domain.PlcEntity.NodeFunction;
import com.cmfi.service.inter.PlanWorkOrderService;
import com.cmfi.utils.SqlAssembly;

/**
 * Service Implementation for managing {@link PlanWorkOrder}.
 */
@Service
public class PlanWorkOrderServiceImpl implements PlanWorkOrderService {

	private static final int STRING = 1;

	private static final int NUMERIC = 0;

	private static final int BOOLEAN = 4;

	private final Logger log = LoggerFactory.getLogger(PlanWorkOrderServiceImpl.class);

	@Autowired
	private PlanWorkOrderDao planWorkOrderRepository;

	@Autowired
	private PlcDao plcDao;

	@Autowired
	private PlcNodeDao plcNodeDao;

	public static BlockingQueue<NodeFunction> plcFinishWorkQueue = new LinkedBlockingQueue<NodeFunction>(1);

	public static AtomicBoolean isSuspendReleaseWorkOrder = new AtomicBoolean(true);
	
	public static ExecutorService threadPoolForSubscribe = Executors.newSingleThreadExecutor();

	@Override
	public PlanWorkOrder save(PlanWorkOrder planWorkOrder) throws Exception {
		log.debug("Request to save PlanWorkOrder : {}", planWorkOrder);
		checkParams(planWorkOrder);
		planWorkOrderRepository.save(planWorkOrder);
		return planWorkOrder;
	}

	/**
	 * Description 参数校验
	 * 
	 * @param planWorkOrder 计划
	 * @throws Exception 异常
	 */
	private void checkParams(PlanWorkOrder planWorkOrder) throws Exception {
		if (planWorkOrder == null) {
			throw new Exception("计划为空！");
		}
		if (planWorkOrder.getGrantrySerialNum() == null) {
			throw new Exception("未传入门架序列号");
		}
	}

	@Override
	public PlanWorkOrder update(PlanWorkOrder planWorkOrder, Long id) throws Exception {
		log.debug("Request to update PlanWorkOrder : {}", planWorkOrder);
		PlanWorkOrder plan = planWorkOrderRepository.findById(id);
		if (plan == null) {
			throw new Exception("待更新的计划不存在");
		}
		planWorkOrder.setId(id);
		planWorkOrderRepository.update(planWorkOrder);
		return planWorkOrder;
	}
	
	@Override
	public List<PlanWorkOrder> findByPage(long pageNum, long pageSize) throws Exception {
		log.info("[PlanWorkOrderServiceImpl][findByPage] pageNum:{},pageSize:{}", pageNum, pageSize);
		Long allNum = planWorkOrderRepository.count();
		long start = 0;
		if (pageNum == 0 && pageSize == 0) {
			start = 0;
			pageSize = allNum;
		} else {
			start = (pageNum - 1) * pageSize;
			if (start > allNum) {
				throw new Exception("请求的页已经不存在");
			}
		}
		List<PlanWorkOrder> planList = planWorkOrderRepository.findByPage(start, pageSize);
		return planList;
	}
	
	@Override
	public List<PlanWorkOrder> findByDateAndPage(String date, long pageNum, long pageSize) throws Exception {
		log.info("[PlanWorkOrderServiceImpl][findByPage] date:{},pageNum:{},pageSize:{}", date, pageNum, pageSize);
//		Map<String, String> conditionMap = new HashMap<>();
//		conditionMap.put("planDate", date);
//		String whereCondition = SqlAssembly.generateWhereConditionsByParams(conditionMap);
//		Long allNumByConditions = forkliftPlanRepository.countByFilterConditions(whereCondition);
		
		List<PlanWorkOrder> countplanWorkOrdersByDate = planWorkOrderRepository.countPlanWorkOrdersByDate(date);
		Long allNum = (long) countplanWorkOrdersByDate.size();
		long start = 0L;
		if (pageNum == 0 && pageSize == 0) {
			start = 0;
			pageSize = allNum;
		} else {
			start = (pageNum - 1) * pageSize;
			if (start > allNum) {
				throw new Exception("请求的页已经不存在");
			}
		}
		List<PlanWorkOrder> planWorkOrdersByDate = planWorkOrderRepository.findByPageAndDate(date, start, pageSize);
		return planWorkOrdersByDate;
	}

//	@Override
//	public List<ForkliftPlan> findByDateAndPage(String date) throws Exception {
//		log.info("[ForkliftPlanServiceImpl][findByPage] date:{}", date);
//		Map<String, String> conditionMap = new HashMap<>();
//		conditionMap.put("planDate", date);
//		String whereCondition = SqlAssembly.generateWhereConditionsByParams(conditionMap);
//		Long allNumByConditions = forkliftPlanRepository.countByFilterConditions(whereCondition);
//		return forkliftPlanRepository.findByPageAndFilterConditions(whereCondition);
//	}
	
	@Override
	public List<PlanWorkOrder> findByDateStatusAndPage(String date, String status, long pageNum, long pageSize)
			throws Exception {
		log.info("[PlanWorkOrderServiceImpl][findByDateStatusAndPage] date:{},pageNum:{},pageSize:{},status:{}", date,
				pageSize, pageSize, status);
		Map<String, String> conditions = new HashMap<>();
		conditions.put("planDate", date);
		conditions.put("status", status);
		String whereCondition = SqlAssembly.generateWhereConditionsByParams(conditions);
		Long allNumByConditions = planWorkOrderRepository.countByFilterConditions(whereCondition);
		long start = 0L;
		if (pageNum == 0 && pageSize == 0) {
			start = 0;
			pageSize = allNumByConditions;
		} else {
			start = (pageNum - 1) * pageSize;
			if (start > allNumByConditions) {
				throw new Exception("请求的页已经不存在");
			}
		}
		return planWorkOrderRepository.findByPageAndFilterConditions(whereCondition, start, pageSize);
	}

	public Long countAll() {
		return planWorkOrderRepository.count();
	}

	public Long countByDate(String date) {
		return planWorkOrderRepository.countByPlanDate(date);
	}

	/**
	 * Description 通过匹配date、status统计个数
	 */
	public Long countByDateAndStatus(String date, String status) {
		if (status.length() == 0 && date.length() == 0) {
			return planWorkOrderRepository.count();
		} else if (date.length() == 0) {
			return planWorkOrderRepository.countByPlanWorkOrderStatus(status);
		} else if (status.length() == 0) {

			return planWorkOrderRepository.countByPlanDate(date);
		} else {
			return planWorkOrderRepository.countByPlanDateAndPlanWorkOrderStatus(date, status);
		}
	}

	@Override
	public PlanWorkOrder findOne(Long id) {
		log.info("[PlanWorkOrderServiceImpl][findOne] id:{}", id);
		return planWorkOrderRepository.findById(id);
	}

	@Override
	public PlanWorkOrder findByVinCode(String vinCode) {
		log.info("[PlanWorkOrderServiceImpl][findByVinCode] vinCode:{}", vinCode);
		return planWorkOrderRepository.findByVinCode(vinCode);
	}

	@Override
	public void delete(Long id) {
		log.info("[PlanWorkOrderServiceImpl][delete] id:{}", id);
		planWorkOrderRepository.deleteById(id);
	}

	@Override
	public PlanWorkOrder importExcel(MultipartFile file) throws IOException {
		Workbook workbook = null;
		PlanWorkOrder plan = new PlanWorkOrder();
		try {
			workbook = new XSSFWorkbook(file.getInputStream());
			Sheet sheet = workbook.getSheetAt(0);// 第一个工作表
			if (sheet == null) {
				throw new IOException();
				//return ;
			}
			int firstRowNum = sheet.getFirstRowNum();
			Iterator<Row> rowIterator = sheet.iterator();
			int firstCellNum = 0;
			int lastCellNum = 0;
			while (rowIterator.hasNext()) {
				Row row = rowIterator.next();
				// 忽略第一行，第一行是标题
				if (row.getRowNum() == firstRowNum) {
					firstCellNum = row.getFirstCellNum();
					lastCellNum = row.getLastCellNum();
					continue;
				}
				List<String> rowDataList = new ArrayList<String>();
				for (int i = firstCellNum; i < lastCellNum; i++) {
					String cellValue = getCellValueAsString(row.getCell(i));
					rowDataList.add(cellValue);
				}
				log.info("[ForkliftPlanServiceImpl][importExcel] rowData:{}", rowDataList);
				plan = generateForkliftPlanByRowData(rowDataList);
//				if(plan.getVinCode() != null && plan.getCreateTime() != null && plan.getProduceNo() != null 
//						&& plan.getSequence() != null && plan.getVinCode() != null 
//						&& plan.getMaterialCode() != null && plan.getMaterialName() != null
//						&& plan.getBomCode() != null && plan.getTonnage() != null){ 
//				    forkliftPlanRepository.save(plan);
				
				if(plan.getProduceNo() != null && plan.getPlanner() != null  
						&& plan.getGrantrySerialNum() != null 
						&& plan.getSource() != null && plan.getOnlineTIme() != null){
				    planWorkOrderRepository.save(plan);    
				}
			}
		} 
	    finally {
			workbook.close();
		}
		return plan;
	}
	
	/**
	 * 解析Excel表格导入工单功能的一部分，解析每一行
	 * @param rowDataList
	 * @return
	 */
	public PlanWorkOrder generateForkliftPlanByRowData(List<String> rowDataList) throws IOException{
		PlanWorkOrder plan = new PlanWorkOrder();
		//设置的顺序必须和表格的顺序一致!!!
		//plan.setLine(rowDataList.get(0));
		plan.setOnlineTIme(Instant.now());
		plan.setProduceNo(rowDataList.get(0));
		plan.setPlanner(rowDataList.get(1));
		plan.setGrantrySerialNum(rowDataList.get(2));
		plan.setSource(rowDataList.get(3));
		return plan;
	}
	

	private String getCellValueAsString(Cell cell) {
		if (cell == null) {
			return null;
		}
		switch (cell.getCellType()) {
		case STRING:
			return cell.getStringCellValue();
		case NUMERIC:
			return String.valueOf((long)cell.getNumericCellValue());
		case BOOLEAN:
			return String.valueOf(cell.getBooleanCellValue());
		default:
			return null;
		}
	}

	
		@Override
		public PlanWorkOrder saveFromMES(String responseBody) throws Exception {
			PlanWorkOrder plan = new PlanWorkOrder();
			
			 // 解析JSON格式的数据
			 JSONObject json = JSONObject.parseObject(responseBody);//把String转换成JSON
			 JSONArray produceNo = json.getJSONArray("produceNo");
			 JSONArray planner = json.getJSONArray("planner");
			 JSONArray grantrySerialNum = json.getJSONArray("grantrySerialNum");
			 JSONArray source = json.getJSONArray("source");
			 
			 //将解析出来的数据放入工单对象中存储
			 plan.setOnlineTIme(Instant.now());
			 plan.setProduceNo(produceNo.toString());
			 plan.setPlanner(planner.toString());
			 plan.setGrantrySerialNum(grantrySerialNum.toString());
			 plan.setSource(source.toString());
			
			 checkParams(plan);
			 planWorkOrderRepository.save(plan);
			 return plan;
		}
}
